package org.example.infrastructure.adapter.repository;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.Contained;
import org.apache.catalina.User;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.example.domain.trade.adapter.repository.ITradeRepository;
import org.example.domain.trade.model.aggregate.GroupBuyOrderAggregate;
import org.example.domain.trade.model.aggregate.GroupBuyTeamSettlementAggregate;
import org.example.domain.trade.model.entity.*;
import org.example.domain.trade.model.valobj.GroupBuyProgressVO;
import org.example.domain.trade.model.valobj.TradeOrderStatusEnumVO;
import org.example.infrastructure.dao.IGroupBuyActivityDao;
import org.example.infrastructure.dao.IGroupBuyOrderDao;
import org.example.infrastructure.dao.IGroupBuyOrderListDao;
import org.example.infrastructure.dao.INotifyTaskDao;
import org.example.infrastructure.dao.po.GroupBuyActivity;
import org.example.infrastructure.dao.po.GroupBuyOrder;
import org.example.infrastructure.dao.po.GroupBuyOrderList;
import org.example.infrastructure.dao.po.NotifyTask;
import org.example.infrastructure.dao.po.base.Page;
import org.example.infrastructure.dcc.DCCService;
import org.example.types.common.Constants;
import org.example.types.enums.ActivityStatusEnumVO;
import org.example.types.enums.GroupByOrderEnumVO;
import org.example.types.enums.ResponseCode;
import org.example.types.exception.AppException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

@Slf4j
@Repository

public class TradeRepository implements ITradeRepository {
    @Resource
    private IGroupBuyOrderDao groupBuyOrderDao;
    @Resource
    private IGroupBuyOrderListDao groupBuyOrderListDao;
    @Resource
    private IGroupBuyActivityDao groupBuyActivityDao;
    @Resource
    private INotifyTaskDao notifyTaskDao;

    @Resource
    private DCCService dccService;

    @Override
    public MarketPayOrderEntity queryNoPayMarketPayOrderByOutTradeNo(String userId, String outTradeNo) {

        GroupBuyOrderList groupBuyOrderListReq=new GroupBuyOrderList();
        groupBuyOrderListReq.setUserId(userId);
        groupBuyOrderListReq.setOutTradeNo(outTradeNo);
        GroupBuyOrderList groupBuyOrderListRes = groupBuyOrderListDao.queryGroupBuyOrderRecordByOutTradeNo(groupBuyOrderListReq);

        if(groupBuyOrderListRes==null)
        {

            return null;
        }
        MarketPayOrderEntity marketPayOrderEntity = MarketPayOrderEntity.builder()
                .teamId(groupBuyOrderListRes.getTeamId())
                .orderId(groupBuyOrderListRes.getOrderId())
                .deductionPrice(groupBuyOrderListRes.getDeductionPrice())
                .tradeOrderStatusEnumVO(TradeOrderStatusEnumVO.valueOf(groupBuyOrderListRes.getStatus()))
                .build();

        return marketPayOrderEntity;
    }

    @Override
    public GroupBuyProgressVO queryGroupBuyProgressVO(String teamId) {
        GroupBuyOrder groupBuyOrder = groupBuyOrderDao.queryGroupBuyProgress(teamId);
        if(groupBuyOrder==null)
        {
            return null;
        }
        GroupBuyProgressVO groupBuyProgressVO = GroupBuyProgressVO.builder()
                .targetCount(groupBuyOrder.getTargetCount())
                .completeCount(groupBuyOrder.getCompleteCount())
                .lockCount(groupBuyOrder.getLockCount())
                .build();
        return groupBuyProgressVO;
    }

    @Transactional(timeout = 500)
    @Override
    public MarketPayOrderEntity lockMarketPayOrder(GroupBuyOrderAggregate groupBuyOrderAggregate) {

        //聚合对象信息
       UserEntity userEntity= groupBuyOrderAggregate.getUserEntity();
        PayActivityEntity payActivityEntity=groupBuyOrderAggregate.getPayActivityEntity();
        PayDiscountEntity payDiscountEntity = groupBuyOrderAggregate.getPayDiscountEntity();
        Integer userTakeOrderCount = groupBuyOrderAggregate.getUserTakeOrderCount();
        // 判断是否有团 - teamId 为空 - 新团、为不空 - 老团
        String teamId = payActivityEntity.getTeamId();
        if (StringUtils.isBlank(teamId)) {
            // 使用 RandomStringUtils.randomNumeric 替代公司里使用的雪花算法UUID
            teamId = RandomStringUtils.randomNumeric(8);
            
            
            Date currentDate=new Date();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(currentDate);
            calendar.add(Calendar.MINUTE,payActivityEntity.getValidTime());

            // 构建拼团订单
            GroupBuyOrder groupBuyOrder = GroupBuyOrder.builder()
                    .teamId(teamId)
                    .activityId(payActivityEntity.getActivityId())
                    .source(payDiscountEntity.getSource())
                    .channel(payDiscountEntity.getChannel())
                    .originalPrice(payDiscountEntity.getOriginalPrice())
                    .deductionPrice(payDiscountEntity.getDeductionPrice())
                    .payPrice(payDiscountEntity.getPayPrice())
                    .targetCount(payActivityEntity.getTargetCount())
                    .validStartTime(currentDate)
                    .validEndTime(calendar.getTime())
                    .notifyUrl(payDiscountEntity.getNotifyUrl())
                    .completeCount(0)
                    .lockCount(1)
                    .build();


            // 写入记录
            groupBuyOrderDao.insert(groupBuyOrder);
        }else
        {
            // 更新记录 - 如果更新记录不等于1，则表示拼团已满，抛出异常
            int updateAddLockCount = groupBuyOrderDao.updateAddLockCount(teamId);
            if(1!= updateAddLockCount){
                throw new AppException(ResponseCode.E0005.getCode(),ResponseCode.E0005.getInfo());
            }
        }

        // 使用 RandomStringUtils.randomNumeric 替代公司里使用的雪花算法UUID
        String orderId=RandomStringUtils.randomNumeric(12);



                GroupBuyOrderList groupBuyOrderListReq = GroupBuyOrderList.builder()
                .userId(userEntity.getUserId())
                .teamId(teamId)
                .orderId(orderId)
                .activityId(payActivityEntity.getActivityId())
                .startTime(payActivityEntity.getStartTime())
                .endTime(payActivityEntity.getEndTime())
                .goodsId(payDiscountEntity.getGoodsId())
                .source(payDiscountEntity.getSource())
                .channel(payDiscountEntity.getChannel())
                .originalPrice(payDiscountEntity.getOriginalPrice())
                .deductionPrice(payDiscountEntity.getDeductionPrice())
                .status(TradeOrderStatusEnumVO.CREATE.getCode())
                .outTradeNo(payDiscountEntity.getOutTradeNo())
                        .bizId(payActivityEntity.getActivityId()+ Constants.UNDERLINE + userEntity.getUserId()+ Constants.UNDERLINE+ (userTakeOrderCount+1))
                .build();


                try{
                    // 写入拼团记录

                    groupBuyOrderListDao.insert(groupBuyOrderListReq);
                }catch (DuplicateKeyException e)
                {
                    throw new AppException(ResponseCode.INDEX_EXCEPTION.getCode(),ResponseCode.INDEX_EXCEPTION.getInfo());


                }



        return MarketPayOrderEntity.builder()
                .teamId(teamId)
                .orderId(orderId)
                .deductionPrice(payDiscountEntity.getDeductionPrice())
                .tradeOrderStatusEnumVO(TradeOrderStatusEnumVO.CREATE)
                .build();
    }

    @Override
    public GroupBuyActivityEntity queryGroupBuyActivityByActivityId(Long activityId) {

        GroupBuyActivity groupBuyActivity=groupBuyActivityDao.queryGroupBuyActivityByActivityId(activityId);

        GroupBuyActivityEntity groupBuyActivityEntity = GroupBuyActivityEntity.builder()
                .activityId(groupBuyActivity.getActivityId())
                .activityName(groupBuyActivity.getActivityName())
                .discountId(groupBuyActivity.getDiscountId())
                .groupType(groupBuyActivity.getGroupType())
                .takeLimitCount(groupBuyActivity.getTakeLimitCount())
                .target(groupBuyActivity.getTarget())
                .validTime(groupBuyActivity.getValidTime())
                .status(ActivityStatusEnumVO.valueOf(groupBuyActivity.getStatus()))
                .startTime(groupBuyActivity.getStartTime())
                .endTime(groupBuyActivity.getEndTime())
                .tagId(groupBuyActivity.getTagId())
                .tagScope(groupBuyActivity.getTagScope())
                .build();

        return groupBuyActivityEntity;
    }

    @Override
    public Integer queryOrderCountBuActivityId(Long activityId, String userId) {
        GroupBuyOrderList groupBuyOrderList=new GroupBuyOrderList();
        groupBuyOrderList.setActivityId(activityId);
        groupBuyOrderList.setUserId(userId);



        return groupBuyOrderListDao.queryOrderCountBuActivityId(groupBuyOrderList);
    }

    @Override
    public GroupBuyTeamEntity queryGroupBuyTeamEntity(String teamId) {

        GroupBuyOrder groupBuyOrder=groupBuyOrderDao.queryGroupBuyTeamEntity(teamId);



        GroupBuyTeamEntity groupBuyTeamEntity = GroupBuyTeamEntity.builder()
                .teamId(groupBuyOrder.getTeamId())
                .activityId(groupBuyOrder.getActivityId())
                .targetCount(groupBuyOrder.getTargetCount())
                .completeCount(groupBuyOrder.getCompleteCount())
                .lockCount(groupBuyOrder.getLockCount())
                .status(GroupByOrderEnumVO.valueOf(groupBuyOrder.getStatus()))
                .validStarTime(groupBuyOrder.getValidStartTime())
                .validEndTime(groupBuyOrder.getValidEndTime())
                .notifyUrl(groupBuyOrder.getNotifyUrl())
                .build();

        return groupBuyTeamEntity;
    }

    @Override
    public void settlementMarketPayOrder(GroupBuyTeamSettlementAggregate groupBuyTeamSettlementAggregate) {
        UserEntity userEntity=groupBuyTeamSettlementAggregate.getUserEntity();
        GroupBuyTeamEntity  groupBuyTeamEntity=groupBuyTeamSettlementAggregate.getGroupBuyTeamEntity();
        TradePaySuccessEntity tradePaySuccessEntity=groupBuyTeamSettlementAggregate.getTradePaySuccessEntity();

        GroupBuyOrderList groupBuyOrderListReq=new GroupBuyOrderList();
        groupBuyOrderListReq.setUserId(userEntity.getUserId());
        groupBuyOrderListReq.setOutTradeNo(tradePaySuccessEntity.getOutTradeNo());
        groupBuyOrderListReq.setOutTradeTime(tradePaySuccessEntity.getOutTradeTime());

        int updateOrderListStatusCount=groupBuyOrderListDao.updateOrderStatus2COMPLETE(groupBuyOrderListReq);
        if(1!=updateOrderListStatusCount)
        {
            throw new AppException(ResponseCode.UPDATE_ZERO.getCode(),ResponseCode.UPDATE_ZERO.getInfo());

        }

        int updateAddCount=groupBuyOrderDao.updateAddCompleteCount(groupBuyTeamEntity.getTeamId());
        if(1!=updateAddCount)
        {
            throw new AppException(ResponseCode.UPDATE_ZERO.getCode(),ResponseCode.UPDATE_ZERO.getInfo());

        }
        if(groupBuyTeamEntity.getTargetCount()-groupBuyTeamEntity.getCompleteCount()==1)
        {
            int updateOrderStatusCount =groupBuyOrderDao.updateOrderStatus2COMPLETE(groupBuyTeamEntity.getTeamId());
            if (1!=updateOrderStatusCount)
            {
                throw new AppException(ResponseCode.UPDATE_ZERO.getCode(),ResponseCode.UPDATE_ZERO.getInfo());
            }
            List<String> outTradeNoList=groupBuyOrderListDao.queryGroupBuyCompleteOrderOutTradeNoListByteamId(groupBuyTeamEntity.getTeamId());
            NotifyTask notifyTask=new NotifyTask();
            notifyTask.setActivityId(groupBuyTeamEntity.getActivityId());
            notifyTask.setTeamId(groupBuyTeamEntity.getTeamId());
            notifyTask.setNotifyUrl(groupBuyTeamEntity.getNotifyUrl());
            notifyTask.setNotifyCount(0);
            notifyTask.setNotifyStatus(0);
            notifyTask.setParameterJson(JSON.toJSONString(new HashMap<String,Object>()
            {{
                put("TeamId",groupBuyTeamEntity.getTeamId());
                put("outTradeNoList",outTradeNoList);
            }


            }));

            notifyTaskDao.insert(notifyTask);



        }


    }

    @Override
    public Boolean isSCBlackIntercept(String source, String channel) {




        return dccService.isSCBlackIntercept(source,channel);
    }

    @Override
    public List<NotifyTaskEntity> queryUnExecuteNotifytaskList() {

        List<NotifyTask> notifyTasksList=notifyTaskDao.queryUnExecuteNotifytaskList();
        if(notifyTasksList.isEmpty())
        {
            return new ArrayList<>();
        }

        List<NotifyTaskEntity> notifyTaskEntities=new ArrayList<>();
        for (NotifyTask notifyTask : notifyTasksList)
        {
            NotifyTaskEntity notifyTaskEntity = NotifyTaskEntity.builder()
                        .teamId(notifyTask.getTeamId())
                        .notifyUrl(notifyTask.getNotifyUrl())
                        .notifyCount(notifyTask.getNotifyCount())
                        .parameterJson(notifyTask.getParameterJson())
                        .build();

            notifyTaskEntities.add(notifyTaskEntity);
        }
        return notifyTaskEntities;
    }

    @Override
    public List<NotifyTaskEntity> queryUnExecuteNotifytaskList(String teamId) {
        NotifyTask notifyTask = notifyTaskDao.queryUnExecutedNotifyTaskByteamId(teamId);
        if(null==notifyTask)
        {
            return  new ArrayList<>();
        }
        NotifyTaskEntity notifyTaskEntity = NotifyTaskEntity.builder()
                .teamId(notifyTask.getTeamId())
                .notifyUrl(notifyTask.getNotifyUrl())
                .notifyCount(notifyTask.getNotifyCount())
                .parameterJson(notifyTask.getParameterJson())
                .build();

        return Collections.singletonList(notifyTaskEntity);

    }

    @Override
    public int updateNotifyTaskStatusSuccess(String teamId) {
        log.info("teamId:{}",teamId);



        return notifyTaskDao.updateNotifyTaskStatusSuccess(teamId);
    }

    @Override
    public int updateNotifyTaskStatusError(String teamId) {
        log.info("teamId:{}",teamId);

        return notifyTaskDao.updateNotifyTaskStatusError(teamId);
    }

    @Override
    public int updateNotifyTaskStatusRetry(String teamId) {
        log.info("teamId:{}",teamId);

        return notifyTaskDao.updateNotifyTaskStatusRetry(teamId);
    }


}
